/* HueShift.h
Michael Zahniser

Header file for the AlphaShift class, which takes an SDL Surface as input
and shifts the hue of the surface by the given amount. The hue can also be
"flipped" - keeping red as red but swapping blue and green.

A HueShift object stores a large lookup table used for the hue mapping, so
the object should be reused throughout the life of a program if possible.
*/

#ifndef __MZ_HUE_SHIFT_H__
#define __MZ_HUE_SHIFT_H__

#include "_sdl/Surface.h"



class HueShift {
public:
	HueShift();

	// Rotate the hues in the given surface by the given angle (in degrees).
	// That is, 60 degrees maps R to Y, G to C, B to M.
	// Optionally flip the hues first (R <-> R, Y <-> M, G <-> B, C <-> C).
	void operator()(Surface &surface, int angle, bool flip = false);


private:
	// Update the lookup table, if necessary, to match the given format.
	void UpdateLUT(const Surface &surface);
	// Check the byte ordering of the given format. Return true if it is different
	// from the byte ordering of the lookup table.
	bool IsNewByteOrder(const Surface &surface);
	// Update the byte indices to match this new format.
	void UpdateByteOrder(const Surface &surface);
	// Given (r, g, b) values and their maximum and range, return a hue in [0, 6 * range).
	static int Hue(int r, int g, int b, int maximum, int range);
	// Map the given hue and saturaton to a color.
	Uint32 Color(int hue, int saturation) const;


private:
	// HUES _must_ be a power of 2.
	static const int HUES = 256;
	// This value really needs to be 256. The code doesn't support anything else.
	static const int SATS = 256;


private:
	// This is the color (1, 2, 3) encoded in the format of the most recent surface.
	// This is used to check when the format has changed.
	Uint32 key;

	// These indices store the byte ordering of the color.
	int ri;
	int gi;
	int bi;
	int ai;

	// These are only needed in the main operator() function, but storing them with the
	// other class members seems to improve access times by making it more likely that
	// they'll share a cache line with the rest of the class.
	Uint32 aMask;
	Uint32 aMaskC;

	// This lookup table maps (sat + hue * SATS) to (r, g, b).
	Uint32 colorLUT[HUES * SATS];
};

#endif
